package com.xiashitech.buildservice.plugin;

import java.io.*;
import java.util.Enumeration;
import java.util.LinkedList;
import java.util.List;
import java.util.jar.JarEntry;
import java.util.jar.JarFile;
import java.util.jar.JarOutputStream;
import java.util.zip.Deflater;

public class InitJar {
    public static void init(String jarName) {
        File sourceFile = new File(jarName);
        if(!sourceFile.exists()) {
            return;
        }
        String newJarName = jarName.replace("-all","");
        deleteFile(newJarName); // 避免出现重新 build 时，文件越来越大的问题
        try (
                JarFile jarFile = new JarFile(sourceFile);
                FileOutputStream fileOutputStream = new FileOutputStream(newJarName, true);
                JarOutputStream jarOutputStream = new JarOutputStream(fileOutputStream);
        ) {
            boolean tempIsDev = jarFile.getJarEntry("com/xiashitech/agent/boot/LoadClassHelper.class") != null;
            System.out.println("build plugin is working for [" + (tempIsDev ? "dev" : "master") + "]");

            List<JarEntry> lists = new LinkedList<>();
            Enumeration<JarEntry> entries = jarFile.entries();
            while (entries.hasMoreElements()) {
                JarEntry jarEntry = entries.nextElement();
                lists.add(jarEntry);
            }
            jarOutputStream.setLevel(Deflater.BEST_COMPRESSION);
            for (JarEntry je : lists) {
                if (je.getName().startsWith("META-INF/native/")) // 过滤掉 grpc 中的 tcnative 和 epoll native 的 so 库
                    continue;

                if(tempIsDev) {
                    if (je.getName().startsWith("com/xiashitech/agent/instrumentation/")
                            && je.getName().contains("/inst/")
                            && je.getName().endsWith(".class")) {
                        // 将内容写入文件中
                        jarOutputStream.putNextEntry(new JarEntry("inst/" + je.getName() + "data"));
                    } else {
                        //表示将该JarEntry写入jar文件中 也就是创建该文件夹和文件
                        jarOutputStream.putNextEntry(new JarEntry(je.getName()));
                    }
                } else {
                    if (je.getName().startsWith("com/xiashitech/") && je.getName().contains("/inst/") && je.getName().endsWith(".class") && !je.getName().startsWith("inst")) {
                        // 将内容写入文件中
                        jarOutputStream.putNextEntry(new JarEntry("inst/" + je.getName() + "data"));
                    } else if ((je.getName().startsWith("com/xiashitech/") && je.getName().contains("/extload/") && !je.getName().contains("/extloadproxy/") || je.getName().startsWith("xiashitech/shade/extload")) && je.getName().endsWith(".class") && !je.getName().startsWith("inst")) {
                        // 将内容写入文件中: 需要外部加载的agent工程里的代码 和 需要外部加载的第三方依赖包
                        jarOutputStream.putNextEntry(new JarEntry(je.getName() + "data"));
                    } else {
                        //表示将该JarEntry写入jar文件中 也就是创建该文件夹和文件
                        jarOutputStream.putNextEntry(new JarEntry(je.getName()));
                    }
                }
                InputStream inputStream = jarFile.getInputStream(je);
                ByteArrayOutputStream outSteam = new ByteArrayOutputStream();
                try {
                    byte[] buffer = new byte[1024];
                    int len;
                    while ((len = inputStream.read(buffer)) != -1) {
                        outSteam.write(buffer, 0, len);
                    }
                    outSteam.close();
                    inputStream.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }

                jarOutputStream.write(outSteam.toByteArray());
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
        //清理临时文件
        deleteFile(jarName);
        deleteFile(newJarName.substring(0,newJarName.indexOf("-"))+"-source.jar");
    }

    private static void deleteFile(String fileName) {
        try {
            File jarFile = new File(fileName);
            if(jarFile.exists()) {
                jarFile.delete();
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}
